home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 4131 < prev    next >
Encoding:
Text File  |  1996-08-06  |  2.9 KB  |  89 lines

  1. Path: news.th-darmstadt.de!news!enno
  2. From: enno@inferenzsysteme.informatik.th-darmstadt.de (Enno Sandner)
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: Two way communication between objects
  5. Date: 28 Jan 1996 10:06:52 GMT
  6. Organization: Fachbereich Informatik, TH Darmstadt
  7. Distribution: world
  8. Message-ID: <ENNO.96Jan28110653@kitz.inferenzsysteme.informatik.th-darmstadt.de>
  9. References: <310ACCE2.2600@werple.mira.net.au>
  10. NNTP-Posting-Host: kitz.intellektik.informatik.th-darmstadt.de
  11. In-reply-to: Ross Forder's message of Sun, 28 Jan 1996 11:09:54 +1000
  12.  
  13. In article <310ACCE2.2600@werple.mira.net.au> Ross Forder <erosco@werple.mira.net.au> writes:
  14.  
  15.    I have to apologise what what is probably a stupid question but I'm only
  16.    a beginner at some of this stuff.
  17.  
  18.    I am trying to write a VERY simple client and server set of objects. I 
  19.    would like to client to register with the server at ctor time and have 
  20.    the server know about the client by saving a pointer to the client 
  21.    so he can callback to a method called say 'event'. 
  22.  
  23.    The problem is the fact that they will both need a pointer to each other 
  24.    and this seems impossible using strong typing. Is there a simple 'object 
  25.    oriented' way to do this?
  26.  
  27.    I have been able to make this work by having the server only know about 
  28.    a parent class of the client (say eventhandler) but this is still not a 
  29.    bulletproof solution.
  30.  
  31.    Can someone set me straight?
  32.  
  33. For circular dependent references one need a so-called forward declaration
  34.  
  35.         struct B;         // declare B ('There is a class B')
  36.         struct A { B* b_; };    // define  A ('A looks like ...')
  37.         struct B { A* a_; };    // define  B ('B looks like ...')
  38.  
  39. In A's definition it's already known that there is a class called 'B'.
  40. So the compiler will not complain about the 'not-yet-defined' class as
  41. long you don't try to access members of B in the definition of 'A'.
  42. These sort of circular dependency can often be avoided when you introduce
  43. an abstract class. A possible solution to your problem (or better a direct
  44. assembly from your description ...) may look like:
  45. ---
  46. #include <iostream.h>
  47.  
  48. class Server;
  49.  
  50. class Client {
  51.  public:
  52.   virtual ~Client() {}
  53.   virtual void Event()=0;
  54.   virtual Server& CreateServer()=0;
  55. };
  56.  
  57. class Server {
  58.  public:
  59.   Server(Client& cb) : cb_(cb) {}
  60.   void NotifyClient() { cb_.Event(); }
  61.  private:
  62.   Client& cb_;
  63. };
  64.  
  65. class ConcrClient : public Client {
  66.  public:
  67.   void Event() { cout << "Event\n"; }
  68.   Server& CreateServer() { return *new Server(*this); }
  69. };
  70.  
  71. int main()
  72. {
  73.   ConcrClient client;
  74.   Server& server=client.CreateServer();
  75.   server.NotifyClient();
  76.   delete &server;
  77.  
  78.   return 0;
  79. }
  80.  
  81. ---
  82. The abstract class 'Client' defines the common interface of all clients.
  83. Thus every client needs an 'Event' member-function. The server accesses
  84. them only through that interface, so it's easy to add new sorts of clients.
  85. There are more flexible ways to implement callbacks, e.g. the 'Command'
  86. pattern described in the 'Design Patterns' book.
  87.  
  88.     Enno
  89.